import CryptoUtil from './utils/crypto.js';

// 跟踪已加载内容脚本的标签页
const contentScriptTabsLoaded = new Set();
const debug = false; // 调试模式开关

// 存储应该自动填充的标签页ID
const autoFillTabIds = new Set();

// 安全的日志函数
function log(message, data) {
    if (debug || message.includes('error') || message.includes('失败') || message.includes('出错')) {
        console.log(message, data ? data : '');
    }
}

// 安全的错误日志函数
function errorLog(message, error) {
    console.error(message, error ? error : '');
}

// 将错误对象转换为可序列化的对象
function serializeError(error) {
    if (!error) return 'Unknown error';
    if (typeof error === 'string') return error;
    
    const serialized = {
        message: error.message || 'No message',
        name: error.name || 'Error'
    };
    
    if (error.stack) {
        serialized.stack = error.stack;
    }
    
    // 添加额外的非标准属性
    for (const key in error) {
        if (typeof error[key] !== 'function' && !serialized[key]) {
            try {
                serialized[key] = String(error[key]);
            } catch (e) {
                serialized[key] = 'Cannot serialize';
            }
        }
    }
    
    return serialized;
}

// 监听内容脚本加载消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    try {
        if (request.type === 'CONTENT_SCRIPT_LOADED' && sender.tab) {
            log('内容脚本已加载，标签页ID:', sender.tab.id);
            contentScriptTabsLoaded.add(sender.tab.id);
            
            // 如果该标签页在自动填充列表中，立即进行填充
            if (autoFillTabIds.has(sender.tab.id)) {
                log('该标签页需要自动填充:', sender.tab.id);
                performAutoFillForTab(sender.tab.id, sender.tab.url);
                // 填充完成后从列表中移除
                autoFillTabIds.delete(sender.tab.id);
            }
            
            sendResponse({ status: 'acknowledged' });
        }
        
        // 从popup界面触发的自动填充请求
        if (request.type === 'REQUEST_AUTO_FILL') {
            log('收到自动填充请求:', request.data);
            
            // 打开新标签页并标记为需要自动填充
            chrome.tabs.create({
                url: request.data.url
            }, tab => {
                // 将新标签页添加到自动填充列表
                autoFillTabIds.add(tab.id);
                
                // 存储该标签页需要的凭据
                chrome.storage.local.set({
                    [`autofill_${tab.id}`]: {
                        username: request.data.username,
                        password: request.data.password
                    }
                });
                
                log('已创建新标签页并准备自动填充:', tab.id);
                sendResponse({ success: true, tabId: tab.id });
            });
            
            return true; // 保持消息通道开放
        }
        
        if (request.type === 'SAVE_CREDENTIALS') {
            log('收到保存凭据消息');
            // 保存新的登录信息
            chrome.storage.sync.get(['masterKey'], async (settings) => {
                try {
                    if (!settings.masterKey) {
                        sendResponse({ success: false, message: '请先设置主密钥' });
                        return;
                    }

                    const crypto = new CryptoUtil(settings.masterKey);
                    const encryptedData = await chrome.storage.local.get('entries');
                    
                    let entries = [];
                    if (encryptedData.entries) {
                        entries = await crypto.decrypt(encryptedData.entries);
                    }

                    const newEntry = {
                        id: Date.now(),
                        url: request.data.url,
                        username: request.data.username,
                        password: request.data.password,
                        notes: request.data.notes || '',
                        createdAt: new Date().toISOString()
                    };

                    entries.push(newEntry);
                    const newEncryptedData = await crypto.encrypt(entries);
                    await chrome.storage.local.set({ entries: newEncryptedData });
                    
                    sendResponse({ success: true });
                } catch (error) {
                    errorLog('保存凭据失败:', serializeError(error));
                    sendResponse({ success: false, message: '保存失败', error: serializeError(error) });
                }
            });
            return true; // 保持消息通道开放
        }
    } catch (error) {
        errorLog('处理消息出错:', serializeError(error));
        sendResponse({ success: false, error: serializeError(error) });
        return true;
    }
});

// 执行特定标签页的自动填充
async function performAutoFillForTab(tabId, tabUrl) {
    try {
        // 首先检查是否有存储的凭据
        const data = await chrome.storage.local.get(`autofill_${tabId}`);
        const credentials = data[`autofill_${tabId}`];
        
        if (credentials) {
            log('找到需要填充的凭据:', tabId);
            
            // 删除存储的凭据
            await chrome.storage.local.remove(`autofill_${tabId}`);
            
            // 发送填充请求
            setTimeout(async () => {
                try {
                    // 确保内容脚本已加载
                    if (await ensureContentScriptLoaded(tabId)) {
                        // 发送自动填充消息
                        const result = await sendAutoFillData(
                            tabId, 
                            credentials.username, 
                            credentials.password
                        );
                        
                        if (result) {
                            log('凭据自动填充成功');
                        } else {
                            log('凭据自动填充失败');
                        }
                    }
                } catch (error) {
                    errorLog('自动填充过程中出错:', serializeError(error));
                }
            }, 1500); // 给页面加载充足时间
        } else {
            // 如果没有存储的凭据，可能是通过URL匹配的方式
            log('没有特定存储的凭据，跳过自动填充');
        }
    } catch (error) {
        errorLog('执行自动填充时出错:', serializeError(error));
    }
}

// 安全地发送消息到内容脚本
async function sendMessageToTab(tabId, message) {
    return new Promise((resolve, reject) => {
        try {
            chrome.tabs.sendMessage(tabId, message, response => {
                if (chrome.runtime.lastError) {
                    const error = {
                        message: chrome.runtime.lastError.message,
                        tabId,
                        messageType: message.type,
                        timestamp: new Date().toISOString()
                    };
                    errorLog('向标签页发送消息时出错:', error);
                    reject(error);
                } else {
                    resolve(response);
                }
            });
        } catch (error) {
            errorLog('发送消息异常:', serializeError(error));
            reject(serializeError(error));
        }
    });
}

// 检查内容脚本是否已加载
async function isContentScriptLoaded(tabId) {
    try {
        const response = await sendMessageToTab(tabId, { type: 'PING' });
        if (response && response.status === 'alive') {
            contentScriptTabsLoaded.add(tabId);
            return true;
        }
        return false;
    } catch (error) {
        log('内容脚本未加载:', error.message);
        return false;
    }
}

// 检查页面是否允许注入脚本
async function canInjectScript(tabId) {
    try {
        const tab = await chrome.tabs.get(tabId);
        // 检查URL是否允许注入脚本（非扩展页面、chrome://等受限页面）
        const restrictedPatterns = ['chrome://', 'chrome-extension://', 'chrome-search://', 'edge://', 'about:'];
        return !restrictedPatterns.some(pattern => tab.url.startsWith(pattern));
    } catch (error) {
        errorLog('检查标签页时出错:', serializeError(error));
        return false;
    }
}

// 注入内容脚本
async function injectContentScript(tabId) {
    try {
        // 检查是否可以注入脚本
        if (!await canInjectScript(tabId)) {
            log('由于URL限制，无法注入脚本');
            return false;
        }
        
        // 使用executeScript注入脚本
        await chrome.scripting.executeScript({
            target: { tabId: tabId },
            files: ['content.js']
        });
        
        log('内容脚本注入成功');
        
        // 等待脚本初始化
        await new Promise(resolve => setTimeout(resolve, 500));
        
        // 确认脚本是否注入成功
        return await isContentScriptLoaded(tabId);
    } catch (error) {
        errorLog('注入内容脚本失败:', serializeError(error));
        return false;
    }
}

// 确保内容脚本已加载
async function ensureContentScriptLoaded(tabId) {
    log('确保内容脚本已加载，标签页ID:', tabId);
    
    // 如果已知内容脚本已加载，直接返回
    if (contentScriptTabsLoaded.has(tabId)) {
        return true;
    }
    
    // 检查内容脚本是否已加载
    if (await isContentScriptLoaded(tabId)) {
        return true;
    }
    
    // 尝试注入内容脚本
    return await injectContentScript(tabId);
}

// 发送自动填充数据到页面
async function sendAutoFillData(tabId, username, password) {
    log('准备发送自动填充数据到标签页:', tabId);
    
    try {
        // 确保内容脚本已加载
        const isLoaded = await ensureContentScriptLoaded(tabId);
        if (!isLoaded) {
            errorLog('无法自动填充：内容脚本未加载');
            return false;
        }
        
        // 发送自动填充消息
        const response = await sendMessageToTab(tabId, {
            type: 'AUTO_FILL',
            data: { username, password }
        });
        
        log('自动填充响应:', response);
        return response && response.success;
    } catch (error) {
        errorLog('自动填充过程中出错:', serializeError(error));
        return false;
    }
}

// 监听标签页更新事件
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
    if (changeInfo.status === 'complete' && tab.url) {
        log('标签页已更新:', tabId, tab.url);
        
        // 检查是否是需要自动填充的标签页
        if (autoFillTabIds.has(tabId)) {
            log('这是需要自动填充的标签页:', tabId);
            
            // 不要尝试在受限页面上注入脚本
            if (!await canInjectScript(tabId)) {
                log('跳过受限URL的自动填充:', tab.url);
                autoFillTabIds.delete(tabId); // 从列表中移除
                return;
            }
            
            // 执行自动填充
            performAutoFillForTab(tabId, tab.url);
        }
    }
});

// 定期同步数据
chrome.alarms.create('syncData', {
    periodInMinutes: 30 // 每30分钟同步一次
});

chrome.alarms.onAlarm.addListener(async (alarm) => {
    if (alarm.name === 'syncData') {
        log('开始后台同步...');
        const settings = await chrome.storage.sync.get(['masterKey', 'syncUrl']);
        if (!settings.masterKey || !settings.syncUrl) {
            log('同步跳过：缺少主密钥或同步URL');
            return;
        }

        log('检索本地数据...');
        try {
            const crypto = new CryptoUtil(settings.masterKey);
            const encryptedData = await chrome.storage.local.get('entries');
            
            if (encryptedData.entries) {
                try {
                    log('正在发送数据到服务器...');
                    const response = await fetch(settings.syncUrl, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify({ data: encryptedData.entries })
                    });

                    if (response.ok) {
                        log('后台同步成功');
                        const responseData = await response.json();
                        log('服务器响应:', responseData);
                    } else {
                        errorLog('同步失败，状态码:', response.status);
                        const errorText = await response.text();
                        errorLog('错误详情:', errorText);
                    }
                } catch (error) {
                    errorLog('后台同步失败:', serializeError(error));
                }
            } else {
                log('没有本地数据需要同步');
            }
        } catch (error) {
            errorLog('同步过程中出错:', serializeError(error));
        }
    }
}); 